package utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.mall.common.exception.AuthFailException;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Date;


/**
 * @author: xrj
 * @date: 2022/5/1 17:34
 * @description:
*/

@Slf4j
@Builder
public class JwtTokenUtils {

    private final static String SECRET = "324iu23094u598ndsofhsiufhaf_+0wq-42q421jiosadiusadiasd";

    public static String creatJwtToken(String msg) {
        String encodeMsg = AESUtil.encrypt(msg);//先对信息进行aes加密(防止被破解） AES 对称加密
        String token;
        ZoneId zoneId = ZoneOffset.systemDefault();
        LocalDateTime expireDate = LocalDateTime.now().plusDays(1);
        token = JWT.create()
                .withIssuer("xrj").withExpiresAt(Date.from(expireDate.atZone(zoneId).toInstant()))
                .withClaim("user", encodeMsg)
                .sign(Algorithm.HMAC256(SECRET));
        if (StringUtils.isBlank(token)){
            throw new AuthFailException("jwt生成token信息失败!");
        }
        log.info("加密后：" + token);
        return token;
    }

    /**
     * 解密jwt并验证是否正确
     */
    public static String freeJwt(String token) {
        DecodedJWT decodedJWT;
        //使用hmac256加密算法
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET))
                .withIssuer("xrj")
                .build();
        decodedJWT = verifier.verify(token);
        if (decodedJWT == null) {
            throw new AuthFailException("token验证失败!");
        }
        log.info("签名人：" + decodedJWT.getIssuer() + " 加密方式：" + decodedJWT.getAlgorithm() + " 携带信息：" + decodedJWT.getClaim("user").asString());
        //获得token的头部，载荷和签名，只对比头部和载荷
        String[] headPayload = token.split("\\.");
        //获得jwt解密后头部
        String header = decodedJWT.getHeader();
        //获得jwt解密后载荷
        String payload = decodedJWT.getPayload();
        if (!header.equals(headPayload[0]) && !payload.equals(headPayload[1])) {
            throw new AuthFailException("token验证失败!");
        }
        return AESUtil.decrypt(decodedJWT.getClaim("user").asString());
    }

    public static void main(String[] args) {
        String encode = creatJwtToken("hello");
        System.out.println("jwt加密:" + encode);
        String plain = freeJwt(encode);
        System.out.println("jwt解密:" + plain);
    }
}
